`timescale 1ns / 1ps

module uart_tx_test(
    input   wire             clk         ,
    input   wire             reset_n     ,
    input   wire             en_flag     , // 开始控制/回读信息
    input   wire             rx_flag     , // 回读信息完毕信号
    input   wire             read_en     , // 控制发送还是回读的钥匙

    input   wire     [11:0]  move_time   ,
    input   wire     [11:0]  angle_1_in  , // 地盘
    input   wire     [11:0]  angle_2_in  , // 大臂
    input   wire     [11:0]  angle_3_in  , // 小臂(读取)
    input   wire     [11:0]  angle_4_in  , // 固定值
    input   wire     [11:0]  angle_5_in  , // 物块转向
    input   wire     [11:0]  angle_6_in  , // 吸力

    output  wire             uart_tx     ,
    output  reg              trans_finish
);

/* 输入变量 */
reg    [3:0]   serve_ID    ; // (可作为状态变脸)
reg    [11:0]  angle_data  ;
reg    [11:0]  time_data   ;

/* 状态变量 */
reg            trans_go    ;
reg            trans_done  ;
reg [3:0]      state       ;

//计算校验模块变量申明
wire [7:0]serve_ID_reg;
wire [3:0]angle_thousand;
wire [3:0]angle_hundred;
wire [3:0]angle_ten;
wire [3:0]angle_one;
wire [3:0]time_thousand;
wire [3:0]time_hundred;
wire [3:0]time_ten;
wire [3:0]time_one;

wire [119:0]    data120     ;
reg  [7:0]      data        ; // 发送数值
reg             send_go     ;
// 要发送的数据
assign  serve_ID_reg    = serve_ID + 8'h2F        ;
assign  data120 = read_en ? {40'h21_44_41_52_50   ,
                             serve_ID_reg         ,
                             24'h30_30_23}
                        :   {8'h21                ,
                            {4'h3,time_one      } ,
                            {4'h3,time_ten      } ,
                            {4'h3,time_hundred  } ,
                            {4'h3,time_thousand } ,
                            8'h54                 ,
                            {4'h3,angle_one     } ,
                            {4'h3,angle_ten     } ,
                            {4'h3,angle_hundred } ,
                            {4'h3,angle_thousand} ,
                            8'h50                 , // #00XP 
                            serve_ID_reg          ,
                            24'h30_30_23};

wire tx_done;
// 串口发送数据
uart_byte_tx uart_byte_tx
(
    .clk        (clk    ),
    .reset_n    (reset_n),
    .send_en    (send_go),
    
    .data_byte  (data   ),
    .baud_set   (3'd4   ),
    .uart_tx    (uart_tx),
    .tx_done    (tx_done),
    .uart_state ()
);

reg    send_data_begin; // 开始发送信号
// 变量重装
always@(posedge clk or negedge reset_n) begin
    if(!reset_n) begin
        serve_ID     <= 4'd7;
        angle_data   <= 1'b0;
        time_data    <= 12'd1000;
        trans_go     <= 1'b0;
        trans_finish <= 1'b0;
        send_data_begin <= 1'b0;
    end else if (en_flag) begin // 开始发送数据
        send_data_begin <= 1'b1;
        if(read_en) begin // 如果是发送回读指令，从6开始（吸盘不需要回读，读不了）
            serve_ID     <= 4'd6;
        end else begin // 如果是发送控制指令，从7开始
            serve_ID     <= 4'd7;
        end
    // send_data_begin 开始发送数据（第一个）
    // trans_done 在控制机械臂模式中，需要连续发送
    // rx_flag    在回读机械臂角度时，需要等待回读信息完成，才能发送开启下一步
    end else if (send_data_begin || trans_done || rx_flag) begin
        send_data_begin <= 1'b0; // 自我产生，自我消灭
        casex (serve_ID)
            4'd7:begin
                angle_data <= angle_1_in;
                time_data  <= 12'd0;
                trans_go   <= 1'b1; //开始送入数据
                serve_ID <= 4'd6;
            end
            4'd6:begin
                angle_data <= angle_2_in;
                time_data  <= move_time;
                trans_go   <= 1'b1; //开始
                serve_ID <= 4'd5;
            end
            4'd5:begin
                angle_data <= angle_3_in;
                time_data  <= move_time;
                trans_go   <= 1'b1; //开始
                serve_ID <= 4'd4;
            end
            4'd4:begin
                angle_data <= angle_4_in;
                time_data  <= move_time;
                trans_go   <= 1'b1; //开始
                serve_ID <= 4'd3;
            end
            4'd3:begin
                angle_data <= angle_5_in;
                time_data  <= move_time;
                trans_go   <= 1'b1; //开始
                serve_ID <= 4'd2;
            end
            4'd2:begin
                angle_data <= angle_6_in;
                time_data  <= move_time;
                trans_go   <= 1'b1; //开始
                serve_ID   <= 4'd1;
            end
            4'd1:begin // 完成任务
                trans_finish <= 1'b1;
                serve_ID <= 4'd7;
            end
            default serve_ID <= 4'd7;
        endcase
    end else begin
        trans_go       <= 1'b0              ;
        trans_finish   <= 1'b0              ;
        send_data_begin<= 1'b0              ; // 不需要
        serve_ID       <= serve_ID          ;
        angle_data     <= angle_data        ;
        time_data      <= time_data         ;
    end
end

// 发送指令控制中心
// send_go 发送8位数据
always@(posedge clk or negedge reset_n) begin
    if(!reset_n)begin
        state      <= 4'b0000;
        send_go    <= 1'b0;
        data       <= 1'b0;
        trans_done <= 1'b0;
    end else if(trans_go || tx_done) begin
        casex (state)
            4'b0000:begin
                data <= data120[7:0];
                send_go <= 1'b1;
                state <= 4'b0001;
            end
            4'b0001:begin
                data <= data120[15:8];
                send_go <= 1'b1;
                state <= 4'b0011;
            end
            4'b0011:begin
                data <= data120[23:16];
                send_go <= 1'b1;
                state <= 4'b0010;
            end
            4'b0010:begin
                data <= data120[31:24];
                send_go <= 1'b1;
                state <= 4'b0110;
            end
            4'b0110:begin
                data <= data120[39:32];
                send_go <= 1'b1;
                state <= 4'b0111;
            end
            4'b0111:begin
                data <= data120[47:40];
                send_go <= 1'b1;
                state <= 4'b0101;
            end
            4'b0101:begin
                data <= data120[55:48];
                send_go <= 1'b1;
                state <= 4'b0100;
            end
            4'b0100:begin
                data <= data120[63:56];
                send_go <= 1'b1;
                state <= 4'b1100;
            end
            4'b1100:begin
                data <= data120[71:64];
                send_go <= 1'b1;
                if(read_en) state <= 4'b1000; // 回读数据只需要72位
                else state <= 4'b1101;
            end
            4'b1101:begin
                data <= data120[79:72];
                send_go <= 1'b1;
                state <= 4'b1111;
            end
            4'b1111:begin
                data <= data120[87:80];
                send_go <= 1'b1;
                state <= 4'b1110;
            end
            4'b1110:begin
                data <= data120[95:88];
                send_go <= 1'b1;
                state <= 4'b1010;
            end
            4'b1010:begin
                data <= data120[103:96];
                send_go <= 1'b1;
                state <= 4'b1011;
            end
            4'b1011:begin
                data <= data120[111:104];
                send_go <= 1'b1;
                state <= 4'b1001;
            end
            4'b1001:begin
                data <= data120[119:112];
                send_go <= 1'b1;
                state <= 4'b1000;
            end
            4'b1000:begin
                state <= 4'b0000;
                if(!read_en) trans_done <= 1'b1; // 如果是发送回读指令,就不需要反馈，反馈值由rx发送完给予
            end
            default: state <= 4'b0000;
        endcase
    end else begin
        send_go    <= 1'b0;
        trans_done <= 1'b0;
        state      <= state;
        data       <= data;
    end
end

b_bcd b_bcd_inst_1(
	.bin_in   (angle_data    ),
    .ones     (angle_one     ),
    .tens     (angle_ten     ),
    .hundreds (angle_hundred ),
    .thousand (angle_thousand)
);

b_bcd b_bcd_inst_2(
	.bin_in   (time_data    ),
    .ones     (time_one     ),
    .tens     (time_ten     ),
    .hundreds (time_hundred ),
    .thousand (time_thousand)
);

endmodule